
#region Imports

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;

#endregion

namespace Justa.Reflection
{
    /// <summary>
    /// 
    /// </summary>
    /// 
    /// <param name="method"></param>
    /// 
    /// <returns></returns>
    /// 
    /// <author>Abel Perez</author>
    /// 
    public delegate object MethodInvoker(MethodInvocation method);

    /// <summary>
    /// 
    /// </summary>
    /// 
    public class InvocationHandler : DynamicProxy
    {
        /// <summary>
        /// 
        /// </summary>
        /// 
        public event MethodInvoker invoker;

        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="target"></param>
        /// <param name="classToProxy"></param>
        /// 
        public InvocationHandler(object target, Type classToProxy) 
            : base(target, classToProxy)
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// 
        /// <param name="msg"></param>
        /// 
        /// <returns></returns>
        /// 
        public override IMessage Invoke(IMessage msg)
        {
            IMethodCallMessage callMessage = (IMethodCallMessage) msg;
            MethodInfo methodInfo = callMessage.MethodBase as MethodInfo;
            object returnValue = null;

            if (invoker != null)
            {
                MethodInvocation invocation = new MethodInvocation(target, methodInfo, callMessage.Args);
                returnValue = invoker(invocation);
            }
            else
            {
                returnValue = callMessage.MethodBase.Invoke(target, callMessage.Args);
            }

            return new ReturnMessage(returnValue, new Object[] { }, 0, callMessage.LogicalCallContext, callMessage);
        }
    }
}